﻿namespace UnityEditor.Graphs.AnimationStateMachine
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEditor;
    using UnityEditor.Graphs;
    using UnityEditorInternal;
    using UnityEngine;

    [CustomEditor(typeof(Transition)), CanEditMultipleObjects]
    public class TransitionInspector : Editor
    {
        private int m_AnyStateSourceIndex;
        private SerializedProperty m_Atomic;
        private ReorderableList m_ConditionList;
        private SerializedProperty m_Conditions;
        private AnimatorController m_Controller;
        private SerializedProperty m_Duration;
        private static List<TransitionConditionMode> m_floatModes;
        private static List<TransitionConditionMode> m_intModes;
        private string m_InvalidTransitionMessage;
        private int m_LayerIndex;
        private int m_MotionSetIndex;
        private SerializedProperty m_Name;
        private SerializedProperty m_Offset;
        private Animator m_PreviewObject;
        private SerializedObject m_SerializedTransition;
        private bool m_SingleTransitionHeader;
        private ReorderableList m_TransitionList;
        private TransitionPreview m_TransitionPreview;
        private static Styles s_Styles;
        public bool showTransitionList = true;
        private const int toggleColumnWidth = 30;

        private List<ConditionEvent> AllConditions(string name, out int currentType, out int currentIndex)
        {
            currentIndex = currentType = -2;
            List<ConditionEvent> list = new List<ConditionEvent>();
            int num = 0;
            for (int i = 0; i < this.m_Controller.GetEventCount(); i++)
            {
                string eventName = this.m_Controller.GetEventName(i);
                int eventType = this.m_Controller.GetEventType(i);
                if (eventType != 0)
                {
                    ConditionEvent item = new ConditionEvent(eventName, eventType);
                    list.Add(item);
                    if (eventName == name)
                    {
                        currentIndex = num;
                        currentType = eventType;
                    }
                    num++;
                }
            }
            return list;
        }

        private void ControllerDirty()
        {
            this.m_TransitionPreview.mustResample = true;
        }

        private void DrawConditionsElement(Rect rect, int index, bool selected, bool focused)
        {
            int count;
            SerializedProperty arrayElementAtIndex = this.m_Conditions.GetArrayElementAtIndex(index);
            TransitionConditionMode intValue = (TransitionConditionMode) arrayElementAtIndex.FindPropertyRelative("m_ConditionMode").intValue;
            EditorGUIUtility.LookLikeControls();
            int num = 3;
            Rect rect2 = new Rect(rect.x, rect.y + 2f, rect.width, rect.height - 5f);
            Rect position = rect2;
            position.xMax -= (rect2.width / 2f) + num;
            Rect rect4 = rect2;
            rect4.xMin += (rect2.width / 2f) + num;
            Rect rect5 = rect4;
            rect5.xMax -= (rect4.width / 2f) + num;
            Rect rect6 = rect4;
            rect6.xMin += (rect4.width / 2f) + num;
            string stringValue = arrayElementAtIndex.FindPropertyRelative("m_ConditionEvent").stringValue;
            int currentType = count = -2;
            List<ConditionEvent> list = this.AllConditions(stringValue, out currentType, out count);
            if (list.Count > 0)
            {
                list.Add(new ConditionEvent(string.Empty, -1));
            }
            if (intValue == TransitionConditionMode.ExitTime)
            {
                count = list.Count;
                currentType = -1;
            }
            list.Add(new ConditionEvent("Exit Time", -1));
            bool flag = false;
            string[] displayedOptions = new string[list.Count];
            for (int i = 0; i < displayedOptions.Length; i++)
            {
                ConditionEvent event2 = list[i];
                displayedOptions[i] = event2.conditionName;
            }
            int num5 = EditorGUI.Popup(position, count, displayedOptions);
            if (num5 != count)
            {
                ConditionEvent event3 = list[num5];
                string conditionName = event3.conditionName;
                ConditionEvent event4 = list[num5];
                currentType = event4.conditionType;
                if (currentType != -1)
                {
                    arrayElementAtIndex.FindPropertyRelative("m_ConditionEvent").stringValue = conditionName;
                    intValue = TransitionConditionMode.Equals;
                }
                if (conditionName == "Exit Time")
                {
                    intValue = TransitionConditionMode.ExitTime;
                }
                arrayElementAtIndex.FindPropertyRelative("m_ConditionMode").intValue = (int) intValue;
                flag = true;
            }
            if ((currentType == 1) || (currentType == 3))
            {
                List<TransitionConditionMode> list2 = (currentType != 1) ? m_intModes : m_floatModes;
                string[] strArray2 = new string[list2.Count];
                for (int j = 0; j < strArray2.Length; j++)
                {
                    strArray2[j] = list2[j].ToString();
                }
                int selectedIndex = 0;
                for (int k = 0; k < strArray2.Length; k++)
                {
                    if (intValue.ToString() == strArray2[k])
                    {
                        selectedIndex = k;
                    }
                }
                EditorGUI.BeginChangeCheck();
                selectedIndex = EditorGUI.Popup(rect5, selectedIndex, strArray2);
                if (EditorGUI.EndChangeCheck() || flag)
                {
                    arrayElementAtIndex.FindPropertyRelative("m_ConditionMode").intValue = list2[selectedIndex];
                }
                EditorGUI.BeginChangeCheck();
                float floatValue = arrayElementAtIndex.FindPropertyRelative("m_EventTreshold").floatValue;
                switch (currentType)
                {
                    case 1:
                        floatValue = EditorGUI.FloatField(rect6, floatValue);
                        break;

                    case 3:
                        floatValue = EditorGUI.IntField(rect6, Mathf.FloorToInt(floatValue));
                        break;
                }
                if (EditorGUI.EndChangeCheck() || flag)
                {
                    arrayElementAtIndex.FindPropertyRelative("m_EventTreshold").floatValue = floatValue;
                }
            }
            else if (currentType == 4)
            {
                string[] strArray3 = new string[] { "true", "false" };
                int num10 = (intValue != TransitionConditionMode.IfNot) ? 0 : 1;
                EditorGUI.BeginChangeCheck();
                num10 = EditorGUI.Popup(rect4, num10, strArray3);
                if (EditorGUI.EndChangeCheck() || flag)
                {
                    arrayElementAtIndex.FindPropertyRelative("m_ConditionMode").intValue = (num10 != 0) ? 2 : 1;
                }
            }
            else
            {
                EditorGUI.BeginChangeCheck();
                float num11 = arrayElementAtIndex.FindPropertyRelative("m_ExitTime").floatValue;
                string str3 = string.Format("{0:0.00}", num11);
                num11 = float.Parse(EditorGUI.DelayedTextField(rect4, str3, "0123456789,.-", EditorStyles.numberField));
                if (EditorGUI.EndChangeCheck() || flag)
                {
                    arrayElementAtIndex.FindPropertyRelative("m_ExitTime").floatValue = num11;
                }
            }
        }

        private void DrawConditionsHeader(Rect headerRect)
        {
            EditorGUIUtility.LookLikeControls();
            GUI.Label(headerRect, EditorGUIUtility.TempContent("Conditions"));
        }

        internal override void DrawHeaderHelpAndSettingsGUI(Rect r)
        {
            if (!this.m_SingleTransitionHeader)
            {
                base.DrawHeaderHelpAndSettingsGUI(r);
            }
            else
            {
                if (EditorGUI.s_HelpIcon == null)
                {
                    EditorGUI.s_HelpIcon = EditorGUIUtility.IconContent("_Help");
                    EditorGUI.s_TitleSettingsIcon = EditorGUIUtility.IconContent("_Popup");
                }
                if (Help.HasHelpForObject(this.m_SerializedTransition.targetObject) && GUI.Button(new Rect(r.width - 36f, r.y + 5f, 14f, 14f), EditorGUI.s_HelpIcon, EditorStyles.inspectorTitlebarText))
                {
                    Help.ShowHelpForObject(this.m_SerializedTransition.targetObject);
                }
                Rect position = new Rect(r.width - 18f, r.y + 5f, 14f, 14f);
                if (EditorGUI.ButtonMouseDown(position, EditorGUI.s_TitleSettingsIcon, FocusType.Native, EditorStyles.inspectorTitlebarText))
                {
                    EditorUtility.DisplayObjectContextMenu(position, this.m_SerializedTransition.targetObject, 0);
                }
            }
        }

        internal override void DrawPreview(Rect previewPosition)
        {
            this.referenceTargetIndex = this.m_TransitionList.index;
            this.OnInteractivePreviewGUI(previewPosition, s_Styles.preBackground);
            if (Event.current.type == EventType.Repaint)
            {
                string infoString = this.GetInfoString();
                if (infoString != string.Empty)
                {
                    infoString = infoString.Replace("\n", "   ");
                    infoString = base.target.name + "\n" + infoString;
                    EditorGUI.DropShadowLabel(new Rect(previewPosition.x, previewPosition.yMax - 50f, previewPosition.width, 45f), infoString);
                }
            }
        }

        private void DrawTransitionElement(Rect rect, int index, bool selected, bool focused)
        {
            Transition transition = base.targets[index] as Transition;
            DrawTransitionElementCommon(rect, transition, selected, focused);
        }

        public static void DrawTransitionElementCommon(Rect rect, Transition transition, bool selected, bool focused)
        {
            rect.xMax -= 60f;
            string name = transition.GetName();
            if (string.IsNullOrEmpty(name))
            {
                name = transition.GetTransitionContentForRect(rect).text;
            }
            bool solo = transition.GetSolo();
            bool mute = transition.GetMute();
            GUI.Label(rect, name);
            rect.xMin = rect.xMax;
            rect.width = 30f;
            solo = GUI.Toggle(rect, solo, string.Empty);
            rect.xMin = rect.xMax;
            rect.width = 30f;
            mute = GUI.Toggle(rect, mute, string.Empty);
            transition.SetSolo(solo);
            transition.SetMute(mute);
        }

        public static void DrawTransitionHeaderCommon(Rect rect)
        {
            rect.xMax -= 60f;
            GUI.Label(rect, "Transitions");
            rect.xMin = rect.xMax;
            rect.width = 30f;
            GUI.Label(rect, "Solo");
            rect.xMin = rect.xMax;
            rect.width = 30f;
            GUI.Label(rect, "Mute");
        }

        public override bool HasPreviewGUI()
        {
            return ((this.m_TransitionPreview != null) && this.m_TransitionPreview.HasPreviewGUI());
        }

        private static void InitStyles()
        {
            if (s_Styles == null)
            {
                s_Styles = new Styles();
            }
        }

        private bool IsPreviewable()
        {
            this.m_InvalidTransitionMessage = string.Empty;
            Transition targetObject = this.m_SerializedTransition.targetObject as Transition;
            Motion motion = (targetObject.GetSrcState() == null) ? null : targetObject.GetSrcState().GetMotion(this.m_MotionSetIndex);
            Motion motion2 = (targetObject.GetDstState() == null) ? null : targetObject.GetDstState().GetMotion(this.m_MotionSetIndex);
            bool flag = targetObject.GetSrcState() == null;
            if ((targetObject.GetSrcState() != null) && (targetObject.GetSrcState().GetSpeed() == 0f))
            {
                this.m_InvalidTransitionMessage = "Cannot preview transition: source state has a speed of 0";
                return false;
            }
            if ((targetObject.GetDstState() != null) && (targetObject.GetDstState().GetSpeed() == 0f))
            {
                this.m_InvalidTransitionMessage = "Cannot preview transition: destination state has a speed of 0";
                return false;
            }
            if (this.m_LayerIndex == 0)
            {
                if (flag)
                {
                    if (motion2 == null)
                    {
                        this.m_InvalidTransitionMessage = "Cannot preview AnyState transition:  destination state does not have motion";
                        return false;
                    }
                }
                else
                {
                    if (motion == null)
                    {
                        this.m_InvalidTransitionMessage = "Cannot preview transition: source state does not have motion";
                        return false;
                    }
                    if (motion2 == null)
                    {
                        this.m_InvalidTransitionMessage = "Cannot preview transition: destination state does not have motion";
                        return false;
                    }
                }
            }
            else if ((motion == null) && (motion2 == null))
            {
                this.m_InvalidTransitionMessage = "Cannot preview transition, must at least have a motion on either source or destination state";
                return false;
            }
            return true;
        }

        public void OnDestroy()
        {
            if (this.m_TransitionPreview != null)
            {
                this.m_TransitionPreview.OnDestroy();
            }
        }

        public void OnDisable()
        {
            if (this.m_TransitionPreview != null)
            {
                this.m_TransitionPreview.OnDisable();
            }
            this.m_Controller.OnAnimatorControllerDirty = (System.Action) Delegate.Remove(this.m_Controller.OnAnimatorControllerDirty, new System.Action(this.ControllerDirty));
        }

        public void OnEnable()
        {
            this.m_TransitionPreview = new TransitionPreview();
            this.m_TransitionList = new ReorderableList(base.targets, typeof(Transition), true, true, false, true);
            this.m_TransitionList.onSelectCallback = new ReorderableList.SelectCallbackDelegate(this.OnSelectTransition);
            this.m_TransitionList.onRemoveCallback = new ReorderableList.RemoveCallbackDelegate(this.OnRemoveTransition);
            this.m_TransitionList.drawElementCallback = new ReorderableList.ElementCallbackDelegate(this.DrawTransitionElement);
            this.m_TransitionList.drawHeaderCallback = new ReorderableList.HeaderCallbackDelegate(TransitionInspector.DrawTransitionHeaderCommon);
            this.m_TransitionList.index = 0;
            this.m_Controller = AnimatorControllerTool.tool.animatorController;
            this.m_PreviewObject = AnimatorControllerTool.tool.previewObject;
            this.m_LayerIndex = AnimatorControllerTool.tool.selectedLayerIndex;
            this.m_MotionSetIndex = this.m_Controller.GetLayerMotionSetIndex(this.m_LayerIndex);
            this.m_Controller.OnAnimatorControllerDirty = (System.Action) Delegate.Combine(this.m_Controller.OnAnimatorControllerDirty, new System.Action(this.ControllerDirty));
            if (m_intModes == null)
            {
                m_intModes = new List<TransitionConditionMode>();
                m_intModes.Add(TransitionConditionMode.Greater);
                m_intModes.Add(TransitionConditionMode.Less);
                m_intModes.Add(TransitionConditionMode.Equals);
                m_intModes.Add(TransitionConditionMode.NotEqual);
            }
            if (m_floatModes == null)
            {
                m_floatModes = new List<TransitionConditionMode>();
                m_floatModes.Add(TransitionConditionMode.Greater);
                m_floatModes.Add(TransitionConditionMode.Less);
            }
            this.SetTransitionToInspect(base.targets[0] as Transition);
        }

        internal override void OnHeaderControlsGUI()
        {
            if (!this.m_SingleTransitionHeader)
            {
                base.OnHeaderControlsGUI();
            }
            else
            {
                Transition targetObject = this.m_SerializedTransition.targetObject as Transition;
                GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true) };
                GUI.Label(GUILayoutUtility.GetRect((float) 0f, (float) 0f, options), targetObject.GetUniqueName());
            }
        }

        internal override void OnHeaderIconGUI(Rect iconRect)
        {
            Texture2D miniThumbnail = AssetPreview.GetMiniThumbnail(base.target);
            GUI.Label(iconRect, miniThumbnail);
        }

        internal override void OnHeaderTitleGUI(Rect titleRect, string header)
        {
            if (!this.m_SingleTransitionHeader)
            {
                Rect rect = titleRect;
                rect.height = 16f;
                GUIContent transitionContentForRect = (base.targets[0] as Transition).GetTransitionContentForRect(rect);
                EditorGUI.LabelField(rect, transitionContentForRect);
                rect.y += 18f;
                EditorGUI.LabelField(rect, base.targets.Length + " " + ((base.targets.Length != 1) ? "Transitions" : "Transition"));
            }
            else
            {
                Rect position = titleRect;
                position.height = 16f;
                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = this.m_Name.hasMultipleDifferentValues;
                string name = EditorGUI.DelayedTextField(position, this.m_Name.stringValue, null, EditorStyles.textField);
                EditorGUI.showMixedValue = false;
                if (EditorGUI.EndChangeCheck())
                {
                    ObjectNames.SetNameSmart(this.m_SerializedTransition.targetObject, name);
                }
            }
        }

        public override void OnInspectorGUI()
        {
            InitStyles();
            if (this.showTransitionList)
            {
                this.m_TransitionList.DoList();
            }
            if (this.m_SerializedTransition != null)
            {
                this.m_SerializedTransition.Update();
                this.m_SingleTransitionHeader = true;
                Editor.DrawHeaderGUI(this, string.Empty);
                this.m_SingleTransitionHeader = false;
                EditorGUILayout.PropertyField(this.m_Atomic, new GUILayoutOption[0]);
                Transition targetObject = this.m_SerializedTransition.targetObject as Transition;
                if (this.IsPreviewable())
                {
                    if (targetObject.GetSrcState() != null)
                    {
                        this.m_TransitionPreview.SetTransition(targetObject, this.m_Controller.GetLayerHumanMask(this.m_LayerIndex), this.m_MotionSetIndex, this.m_PreviewObject);
                    }
                    else
                    {
                        List<UnityEditorInternal.State> statesRecursive = this.m_Controller.GetLayerStateMachine(this.m_LayerIndex).statesRecursive;
                        string[] displayedOptions = new string[statesRecursive.Count];
                        int index = 0;
                        foreach (UnityEditorInternal.State state in statesRecursive)
                        {
                            displayedOptions[index] = state.GetName();
                            index++;
                        }
                        EditorGUILayout.Space();
                        this.m_AnyStateSourceIndex = EditorGUILayout.Popup("Preview source state", this.m_AnyStateSourceIndex, displayedOptions, new GUILayoutOption[0]);
                        EditorGUILayout.Space();
                        this.m_TransitionPreview.SetAnyStateTransition(targetObject, statesRecursive[this.m_AnyStateSourceIndex], this.m_Controller.GetLayerHumanMask(this.m_LayerIndex), this.m_MotionSetIndex, this.m_PreviewObject);
                    }
                    this.m_TransitionPreview.DoTransitionPreview();
                }
                else
                {
                    EditorGUILayout.LabelField(this.m_InvalidTransitionMessage, new GUILayoutOption[0]);
                    EditorGUILayout.PropertyField(this.m_Duration, new GUILayoutOption[0]);
                    EditorGUILayout.PropertyField(this.m_Offset, new GUILayoutOption[0]);
                }
                EditorGUI.indentLevel = 0;
                GUILayout.Space(10f);
                if (this.m_ConditionList != null)
                {
                    this.m_ConditionList.DoList();
                }
                this.m_SerializedTransition.ApplyModifiedProperties();
            }
        }

        public override void OnInteractivePreviewGUI(Rect r, GUIStyle background)
        {
            if (this.m_TransitionPreview != null)
            {
                this.m_TransitionPreview.OnInteractivePreviewGUI(r, background);
            }
        }

        public override void OnPreviewSettings()
        {
            if (this.m_TransitionPreview != null)
            {
                this.m_TransitionPreview.OnPreviewSettings();
            }
        }

        private void OnRemoveTransition(ReorderableList list)
        {
            int index = list.index;
            if (list.index >= (list.list.Count - 1))
            {
                list.index = list.list.Count - 1;
            }
            Transition transition = base.targets[index] as Transition;
            AnimatorController.lastActiveController.GetLayerStateMachine(AnimatorControllerTool.tool.selectedLayerIndex).RemoveTransition(transition);
            AnimatorControllerTool.tool.RebuildGraph();
            GUIUtility.ExitGUI();
        }

        private void OnSelectTransition(ReorderableList list)
        {
            this.SetTransitionToInspect(base.targets[list.index] as Transition);
        }

        private void SetTransitionToInspect(Transition transition)
        {
            if ((this.m_SerializedTransition == null) || (this.m_SerializedTransition.targetObject != transition))
            {
                this.m_SerializedTransition = new SerializedObject(transition);
                if (this.m_SerializedTransition != null)
                {
                    this.m_Conditions = this.m_SerializedTransition.FindProperty("m_Conditions");
                    this.m_ConditionList = new ReorderableList(this.m_SerializedTransition, this.m_Conditions);
                    this.m_ConditionList.drawElementCallback = new ReorderableList.ElementCallbackDelegate(this.DrawConditionsElement);
                    this.m_ConditionList.drawHeaderCallback = new ReorderableList.HeaderCallbackDelegate(this.DrawConditionsHeader);
                    this.m_Name = this.m_SerializedTransition.FindProperty("m_Name");
                    this.m_Atomic = this.m_SerializedTransition.FindProperty("m_Atomic");
                    this.m_Duration = this.m_SerializedTransition.FindProperty("m_TransitionDuration");
                    this.m_Offset = this.m_SerializedTransition.FindProperty("m_TransitionOffset");
                }
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ConditionEvent
        {
            public string conditionName;
            public int conditionType;
            public ConditionEvent(string n, int t)
            {
                this.conditionName = n;
                this.conditionType = t;
            }
        }

        private class Styles
        {
            public readonly GUIStyle background = new GUIStyle("IN Label");
            public readonly GUIStyle boxBackground = "TE NodeBackground";
            public readonly GUIStyle draggingHandle = "WindowBottomResize";
            public readonly GUIStyle footerBackground = "preLabel";
            public readonly GUIStyle headerBackground = "TE Toolbar";
            public GUIContent iconToolbarMinus = EditorGUIUtility.IconContent("Toolbar Minus", "Remove selection from list");
            public GUIContent iconToolbarPlus = EditorGUIUtility.IconContent("Toolbar Plus", "Add to list");
            public GUIStyle preBackground = "preBackground";
            public readonly GUIStyle preButton = "preButton";
        }
    }
}

